﻿Imports System.Threading

Public Class Karnel
    Implements IOperationProxy


    Private WithEvents StorageManager As New StorageManager
    Private WithEvents PluginManager As New PluginManager
    Private WithEvents Notificator As New Notificator
    Private WithEvents AlertGroupManager As New AlertGroupManager

    Private LiveProgramDictionary As New Dictionary(Of Integer, LiveProgram)
    Private LiveProgramSlimLock As New ReaderWriterLockSlim


    Private WithEvents Client As IClient

    Public Sub Run()

        'Dim s = New Settings
        's.Add("a", "AAA")
        'StorageManager.SetPluginSettings(Guid.NewGuid, s)

        'Dim list = New List(Of LiveProgram)
        'list.Add(New LiveProgram)
        'StorageManager.SetLivePrograms(list)
        'StorageManager.Save()

        AlertGroupManager.Initialize(StorageManager.GetAlertGroups)

        Client = New Client.MainForm
        Client.Initialize(Me, Nothing)
        PluginManager.ReloadAsync()

        Application.EnableVisualStyles()

        Dim w = New Client.AlertGroupForm
        w.Show()

        Application.Run(DirectCast(Client, Form))
    End Sub

#Region "IOperationProxy"

    Public Sub AddFavorite(ByVal id As String) Implements IOperationProxy.AddFavorite

        LiveProgramSlimLock.EnterReadLock()
        Dim ps = From p In LiveProgramDictionary.Values
                 Where p.Station.Id = id

        For Each p In ps
            p.Station.IsFavorite = True
            p.IsAlerted = True ' アラートに設定しておく（プラグインに通知はしない）
        Next
        LiveProgramSlimLock.ExitReadLock()

        Client.AddFavorite(id)
        ' TODO 保存
    End Sub

    Public Sub Alert(ByVal pluginId As System.Guid, ByVal program As LiveProgram, ByVal state As Object) Implements IOperationProxy.Alert

    End Sub

    Public Function GetFavoriteLivePrograms() As System.Collections.Generic.IList(Of LiveProgram) Implements IOperationProxy.GetFavoriteLivePrograms

    End Function

    Public Function GetOnAirLivePrograms() As System.Collections.Generic.IList(Of LiveProgram) Implements IOperationProxy.GetOnAirLivePrograms

    End Function

    Public Sub RemoveFavorite(ByVal id As String) Implements IOperationProxy.RemoveFavorite

    End Sub

    Public Sub ShowClient() Implements IOperationProxy.ShowClient
        Client.ShowClient()
    End Sub

    Public Sub HideClient() Implements IOperationProxy.HideClient
        Client.HideClient()
    End Sub

    Public Sub CloseClient() Implements IOperationProxy.CloseClient
        Client.CloseClient()
        Notificator.End()
        Application.Exit()
    End Sub

    Public Sub ShowAlertGroupClient() Implements IOperationProxy.ShowAlertGroupClient

    End Sub

    Public Sub ChangeAlertGroup(ByVal stationId As String, ByVal alertGroupId As System.Guid) Implements IOperationProxy.ChangeAlertGroup

    End Sub
#End Region

    Private Sub PluginManager_LoadCompleted(ByVal sender As Object, ByVal e As System.EventArgs) Handles PluginManager.LoadCompleted
        For Each p In PluginManager.Plugins
            p.CreateInstance()
            p.IsEnabled = True
        Next

        Notificator.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Creative AutoUpdate v1.20.00)"
        Notificator.Start()
    End Sub

    Private Sub Notificator_LiveProgramClosed(ByVal sender As Object, ByVal e As LiveProgramIdEventArgs) Handles Notificator.LiveProgramClosed
        Try
            LiveProgramSlimLock.EnterReadLock()
            If Not LiveProgramDictionary.ContainsKey(e.Id) Then
                Exit Sub
            End If
        Catch ex As Exception
        Finally
            LiveProgramSlimLock.ExitReadLock()
        End Try

        Dim ps = From p In PluginManager.Plugins
           Where (p.Kind And PluginKinds.Woeker) = PluginKinds.Woeker _
           AndAlso p.IsEnabled

        For Each p In ps
            DirectCast(p.Plugin, IWorkerPlugin).NotifyLiveProgramClosed(e.Id)
        Next

        Client.NotifyLiveProgramClosed(e.Id)

        LiveProgramSlimLock.EnterWriteLock()
        LiveProgramDictionary.Remove(e.Id)
        LiveProgramSlimLock.ExitWriteLock()

    End Sub

    Private Sub Notificator_LiveProgramPreviewStart(ByVal sender As Object, ByVal e As PreviewLiveProgramEventArgs) Handles Notificator.LiveProgramPreviewStart
        InsertOrUpdateLiveProgram(e.LiveProgram)
        Dim program = LiveProgramDictionary(e.LiveProgram.Id)
        Dim notification = New LiveProgramNotification(program)

        ' Plugins 通知
        Dim ps = From p In PluginManager.Plugins
                 Where (p.Kind And PluginKinds.Woeker) = PluginKinds.Woeker _
                 AndAlso p.IsEnabled

        For Each p In ps
            DirectCast(p.Plugin, IWorkerPlugin).NotifyLiveProgramPreviewStart(notification)
        Next

        ' Client 通知
        If Not notification.Handle Then
            Client.NotifyLiveProgramPreviewStart(notification)
        End If

        ' Alert 
        If Not notification.Alerted Then
            Exit Sub
        End If

        For Each p In ps
            DirectCast(p.Plugin, IWorkerPlugin).NotifyLiveProgramAlerted(program.Id)
        Next
        Client.NotifyLiveProgramAlerted(program.Id)

    End Sub

    Private Sub Notificator_LiveProgramStartedOrUpdated(ByVal sender As Object, ByVal e As LiveProgramEventArgs) Handles Notificator.LiveProgramStartedOrUpdated
        NotifyStartedOrUpdatedLiveProgram(e.LiveProgram)
    End Sub

    Private Sub Notificator_LiveProgramUpdated(ByVal sender As Object, ByVal e As LiveProgramEventArgs) Handles Notificator.LiveProgramUpdated
        NotifyStartedOrUpdatedLiveProgram(e.LiveProgram)
    End Sub

    Private Sub NotifyStartedOrUpdatedLiveProgram(ByVal updatedProgram As LiveProgram)
        InsertOrUpdateLiveProgram(updatedProgram)
        Dim program = LiveProgramDictionary(updatedProgram.Id)
        Dim notification = New LiveProgramNotification(program)

        ' Plugins 通知
        Dim ps = From p In PluginManager.Plugins
                 Where (p.Kind And PluginKinds.Woeker) = PluginKinds.Woeker _
                 AndAlso p.IsEnabled

        For Each p In ps
            DirectCast(p.Plugin, IWorkerPlugin).NotifyLiveProgramStartedOrUpdated(notification)
        Next

        ' Client 通知
        If Not notification.Handle Then
            Client.NotifyLiveProgramStartedOrUpdated(notification)
        End If

        ' Alert 
        If Not notification.Alerted OrElse program.IsAlerted Then
            Exit Sub
        End If
        program.IsAlerted = True

        For Each p In ps
            DirectCast(p.Plugin, IWorkerPlugin).NotifyLiveProgramAlerted(program.Id)
        Next
        Client.NotifyLiveProgramAlerted(program.Id)
    End Sub

    Private Sub InsertOrUpdateLiveProgram(ByVal program As LiveProgram)
        Dim p As LiveProgram = Nothing

        Try
            LiveProgramSlimLock.EnterUpgradeableReadLock()

            If LiveProgramDictionary.ContainsKey(program.Id) Then
                p = LiveProgramDictionary(program.Id)
                Exit Try
            End If

            LiveProgramSlimLock.EnterWriteLock()
            p = DirectCast(program.Clone, LiveProgram)
            LiveProgramDictionary.Add(program.Id, p)
            LiveProgramSlimLock.ExitWriteLock()

        Catch ex As Exception
        Finally
            LiveProgramSlimLock.ExitUpgradeableReadLock()
        End Try

        If (program.AvailableProperties And LiveProgramProperties.Id) = LiveProgramProperties.Id Then
            p.Id = program.Id
        End If
        If (program.AvailableProperties And LiveProgramProperties.Title) = LiveProgramProperties.Title Then
            p.Title = program.Title
        End If
        If (program.AvailableProperties And LiveProgramProperties.Description) = LiveProgramProperties.Description Then
            p.Description = program.Description
        End If
        If (program.AvailableProperties And LiveProgramProperties.CasterName) = LiveProgramProperties.CasterName Then
            p.CasterName = program.CasterName
        End If
        If (program.AvailableProperties And LiveProgramProperties.CasterId) = LiveProgramProperties.CasterId Then
            p.CasterId = program.CasterId
        End If
        If (program.AvailableProperties And LiveProgramProperties.VisitorCount) = LiveProgramProperties.VisitorCount Then
            p.VisitorCount = program.VisitorCount
        End If
        If (program.AvailableProperties And LiveProgramProperties.CommentCount) = LiveProgramProperties.CommentCount Then
            p.CommentCount = program.CommentCount
        End If
        If (program.AvailableProperties And LiveProgramProperties.StartDateTime) = LiveProgramProperties.StartDateTime Then
            p.StartDateTime = program.StartDateTime
        End If
        If (program.AvailableProperties And LiveProgramProperties.OfficialTag) = LiveProgramProperties.OfficialTag Then
            p.OfficialTag = program.OfficialTag
        End If
        If (program.AvailableProperties And LiveProgramProperties.Kinds) = LiveProgramProperties.Kinds Then
            p.Kinds = p.Kinds Or program.Kinds
        End If
        If (program.AvailableProperties And LiveProgramProperties.IsOnAir) = LiveProgramProperties.IsOnAir Then
            p.IsOnAir = program.IsOnAir
        End If
        If (program.AvailableProperties And LiveProgramProperties.IsAlerted) = LiveProgramProperties.IsAlerted Then
            p.IsAlerted = If(program.IsAlerted, True, p.IsAlerted)
        End If
        If (program.AvailableProperties And LiveProgramProperties.CrawlingDateTime) = LiveProgramProperties.CrawlingDateTime Then
            p.CrawlingDateTime = program.CrawlingDateTime
        End If
        If (program.AvailableProperties And LiveProgramProperties.Uri) = LiveProgramProperties.Uri Then
            p.Uri = program.Uri
        End If


        ' Station
        p.Station.Id = program.Station.Id
        p.Station.IsFavorite = program.Station.IsFavorite
        p.Station.Name = program.Station.Name
        p.Station.IconUri = program.Station.IconUri
        ' TODO all copy

    End Sub


End Class
